/*
 * MIT License
 *
 * Copyright (c) 2024-2048 冰羽
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package cn.star.framework.gen.model;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.star.framework.core.IEntity;
import cn.star.framework.gen.core.AbstractJavaCodeModel;
import cn.star.framework.gen.model.field.EntityField;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * 实体模型<br>
 *
 * @author zhaoweiping
 *     <p style='color: red'>Created on 2024-09-23 11:06:00
 * @since 3.0.0
 */
@Slf4j
public class EntityModel extends AbstractJavaCodeModel {
  /** 包名 */
  @Getter @Setter private String packageName;
  /** 表名 */
  @Getter @Setter private String table;

  /** {@link EntityField} */
  @Setter private List<EntityField> fields;

  /** 索引 */
  @Setter private Map<String, List<String>> indexesColumnMap;

  /** 唯一约束 */
  @Setter private Map<String, List<String>> uniquesColumnMap;

  /** 主键列表 */
  @Setter private List<String> primaryKeyColumns;

  /** 注释 */
  @Getter @Setter private String comment;
  /** 实体父类 */
  @Getter @Setter private Class<? extends IEntity> superEntityClass = IEntity.class;

  public EntityModel(String name) {
    super(name);
  }

  @Override
  public String getPackageName() {
    if (StrUtil.isNotBlank(packageName)) {
      return packageName;
    }
    return this.getPackageName("entity");
  }

  public String getTable() {
    if (StrUtil.isBlank(table)) {
      return StrUtil.toUnderlineCase(this.getName());
    }

    return table;
  }

  public List<EntityField> getFields() {
    return fields == null
        ? new ArrayList<>()
        : CollectionUtil.sort(fields, Comparator.comparingInt(EntityField::getOrder));
  }

  public EntityModel packageName(String packageName) {
    this.packageName = packageName;
    return this;
  }

  public EntityModel table(String table) {
    this.table = table;
    return this;
  }

  public EntityModel comment(String comment) {
    this.comment = comment;
    return this;
  }

  public EntityModel superEntityClass(Class<? extends IEntity> superEntityClass) {
    this.superEntityClass = superEntityClass;
    return this;
  }

  public EntityModel addEntityFields(EntityField... fields) {
    List<EntityField> list = this.getFields();
    if (ArrayUtil.isNotEmpty(fields)) {
      for (EntityField field : fields) {
        EntityField p =
            list.stream()
                .filter(item -> item.getName().equals(field.getName()))
                .findFirst()
                .orElse(null);
        if (p == null) {
          list.add(field);
        }
      }
    }

    return this;
  }

  public List<String> getPrimaryKeyColumns() {
    return primaryKeyColumns == null ? new ArrayList<>() : primaryKeyColumns;
  }

  public EntityModel addPrimaryKeyColumns(String... columns) {
    List<String> list = this.getPrimaryKeyColumns();
    if (ArrayUtil.isNotEmpty(columns)) {
      for (String str : columns) {
        if (StrUtil.isNotBlank(str) && list.contains(str)) {
          continue;
        }

        list.add(str);
      }
    }

    return this;
  }

  public Map<String, List<String>> getIndexesColumnMap() {
    return indexesColumnMap == null ? new HashMap<>() : indexesColumnMap;
  }

  public Map<String, List<String>> getUniquesColumnMap() {
    return uniquesColumnMap == null ? new HashMap<>() : uniquesColumnMap;
  }

  public EntityModel addUniqueColumns(String name, String[] columns) {
    return this.addNormalColumns(this.getUniquesColumnMap(), name, columns);
  }

  public EntityModel addIndexColumns(String name, String[] columns) {
    return this.addNormalColumns(this.getIndexesColumnMap(), name, columns);
  }

  private EntityModel addNormalColumns(
      Map<String, List<String>> map, String name, String[] columns) {
    List<String> list = map.get(name);
    if (list == null) {
      list = new ArrayList<>();
    }
    if (ArrayUtil.isNotEmpty(columns)) {
      for (String column : columns) {
        String p = list.stream().filter(item -> item.equals(column)).findFirst().orElse(null);
        if (p == null) {
          list.add(column);
        }
      }
    }
    map.put(name, list);

    return this;
  }
}
